<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/%E6%AD%A6%E6%B1%8932x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/%E6%AD%A6%E6%B1%8916x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib1/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib1/pace/pace-theme-center-simple.min.css">
  <script src="/lib1/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="前言最近一直在参加春招实习面试，面试过程中发现，有时候有些知识虽然看了很多的内容，看过很多深入原理的技术博客解释，但在面试官询问时，往往因为看得太多而不知道该如何抓住重点去回答问题，同时也只看了别人的理解，没办法很流畅通俗地用自己的话语将其完整、流畅地表达出来。emmm，正是因为这个原因，所以萌生了写一篇自己理解的想法，主要还是为了让自己能对每个问题都有自己的认知和总结吧。首先希望能用尽可能简洁的">
<meta property="og:type" content="article">
<meta property="og:title" content="一句化回答JS问题">
<meta property="og:url" content="http://example.com/2021/07/06/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/index.html">
<meta property="og:site_name" content="Technological Blog">
<meta property="og:description" content="前言最近一直在参加春招实习面试，面试过程中发现，有时候有些知识虽然看了很多的内容，看过很多深入原理的技术博客解释，但在面试官询问时，往往因为看得太多而不知道该如何抓住重点去回答问题，同时也只看了别人的理解，没办法很流畅通俗地用自己的话语将其完整、流畅地表达出来。emmm，正是因为这个原因，所以萌生了写一篇自己理解的想法，主要还是为了让自己能对每个问题都有自己的认知和总结吧。首先希望能用尽可能简洁的">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/image/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/v2-0077e57c58c08c97d8010db0d1ec2d8d_720w.jpg">
<meta property="og:image" content="http://example.com/image/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/v2-97a63d2d5761c188ae32b84174e7d2e9_720w.jpg">
<meta property="article:published_time" content="2021-07-06T13:28:16.000Z">
<meta property="article:modified_time" content="2021-11-05T08:13:56.477Z">
<meta property="article:author" content="Li Yudong">
<meta property="article:tag" content="面试总结">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/image/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/v2-0077e57c58c08c97d8010db0d1ec2d8d_720w.jpg">

<link rel="canonical" href="http://example.com/2021/07/06/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>一句化回答JS问题 | Technological Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Technological Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">IT小白的成长之旅</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="tags fa-fw"></i>标签<span class="badge">18</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="th fa-fw"></i>分类<span class="badge">14</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="archive fa-fw"></i>归档<span class="badge">95</span></a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/tiarmor1" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/07/06/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          一句化回答JS问题
        </h1>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2021-07-06 21:28:16" itemprop="dateCreated datePublished" datetime="2021-07-06T21:28:16+08:00">2021-07-06</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-05 16:13:56" itemprop="dateModified" datetime="2021-11-05T16:13:56+08:00">2021-11-05</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2/" itemprop="url" rel="index"><span itemprop="name">前端页面</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
        <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>最近一直在参加春招实习面试，面试过程中发现，有时候有些知识虽然看了很多的内容，看过很多深入原理的技术博客解释，但在面试官询问时，往往因为看得太多而不知道该如何抓住重点去回答问题，同时也只看了别人的理解，没办法很流畅通俗地用自己的话语将其完整、流畅地表达出来。emmm，正是因为这个原因，所以萌生了写一篇自己理解的想法，主要还是为了让自己能对每个问题都有自己的认知和总结吧。首先希望能用尽可能简洁的语言来陈述自己的理解，后面再对整个知识点进行解释吧。大概会连续水很多篇吧，根据面试时问题的方向来进行分类，只记录自己曾遇到的，或者特别常见的问题吧。第一篇就是最重要的JavaScript吧。</p>
<h2 id="1、JS的数据类型"><a href="#1、JS的数据类型" class="headerlink" title="1、JS的数据类型"></a>1、JS的数据类型</h2><p><strong>JS的数据类型主要分为两类吧；一是基础类型也就是值类型，二是引用类型。基础类型主要有：String、Number、Boolean、Null、Undefined、Symbol(ES6新增)。引用类型基本都是对象Object的引申吧，包括Object、Function、Date、Array、RegExp；Map、Set是ES6新增的数据结构。</strong></p>
<p>知识点扩充：基本类型保存再栈中，值不可变、但可以重新赋值，是值之间的比较。引用类型保存再堆中，值可变，是引用的比较。这里往往会引出深浅拷贝的问题，因为不用拷贝来进行复制对象时，由于传递的是值的引用，因此指向的是同一对象。</p>
<h2 id="2、深拷贝、浅拷贝"><a href="#2、深拷贝、浅拷贝" class="headerlink" title="2、深拷贝、浅拷贝"></a>2、深拷贝、浅拷贝</h2><p><strong>深浅拷贝都是对引用类型的复制。浅拷贝只拷贝一层，对于深层次的对象级别，仍然会拷贝引用；而深拷贝能够拷贝多层次的嵌套对象。</strong></p>
<p>知识点扩充：浅拷贝的方法，很简单明了，一层复制即可。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">simpleCopy</span> (<span class="params">obj1</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> obj2 = <span class="built_in">Array</span>.isArray(obj1) ? [] : &#123;&#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i <span class="keyword">in</span> obj1) &#123;</span><br><span class="line">        obj2[i] = obj1[i]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> obj2</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>深拷贝的方法：1、JSON.parse(JSON.stringify());先转换成JSON对象，再转换回来，也很简单明了，但有些情况不适用。</p>
<p>2、循环递归调用即可。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">deepClone</span>(<span class="params">obj</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> objClone = <span class="built_in">Array</span>.isArray(obj) ? [] : &#123;&#125;;</span><br><span class="line">    <span class="keyword">if</span> (obj &amp;&amp; <span class="keyword">typeof</span> obj === <span class="string">"object"</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (key <span class="keyword">in</span> obj) &#123;</span><br><span class="line">            <span class="keyword">if</span> (obj.hasOwnProperty(key)) &#123;</span><br><span class="line">                <span class="comment">//用for..in循环会获取原型链上的可枚举属性，因此需要再用hasOwnProperty来过滤</span></span><br><span class="line">                <span class="keyword">if</span> (obj[key] &amp;&amp; <span class="keyword">typeof</span> obj[key] === <span class="string">'object'</span>) &#123;</span><br><span class="line">                    objectClone[key] = deepClone(obj[key]);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    objClone[key] = obj[key];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> objClone;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3、判断数据类型"><a href="#3、判断数据类型" class="headerlink" title="3、判断数据类型"></a>3、判断数据类型</h2><p><strong>一般使用typeof、instanceof，或者使用object.tostring方法，从而判断数据类型。</strong></p>
<p>typeof 是一个操作符，其右侧跟一个一元表达式，并返回这个表达式的数据类型。对于null、array不能判断。</p>
<p>instanceof 可以正确判断对象的数据类型，用来判断 A 是否为 B 的实例;内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。</p>
<p>toString()：是 Object 的原型方法，调用该方法，默认返回当前对象的 [[Class]] 。</p>
<p>这是一个内部属性，其格式为 [object xxx] ，其中 xxx 就是对象的类型。对于 Object 对象，直接调用 toString() 就能返回 [object Object] 。而对于其他对象，则需要通过 call / apply 来调用才能返回正确的类型信息。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="number">1</span>);  <span class="comment">//'[object Number]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="string">'1'</span>); <span class="comment">//'[object String]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="literal">NaN</span>); <span class="comment">//'[object Number]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(foo);  <span class="comment">//'[object Function]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]); <span class="comment">//'[object Array]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="literal">undefined</span>); <span class="comment">//'[object Undefined]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="literal">null</span>); <span class="comment">//'[object Null]'</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(<span class="literal">true</span>); <span class="comment">//'[object Boolean]'</span></span><br></pre></td></tr></table></figure>

<h2 id="4、数组常见API"><a href="#4、数组常见API" class="headerlink" title="4、数组常见API"></a>4、数组常见API</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr3 = arr1.concat(arr2);<span class="comment">//合并且返回副本</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> bar = [<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>];</span><br><span class="line"><span class="built_in">Array</span>.from(bar);<span class="comment">//from()方法返回一个新的数组迭代器对象，该对象包含数组中每个索引的键/值对</span></span><br><span class="line"><span class="keyword">let</span> dp = <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Array</span>(length1), ()=&gt; &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="built_in">Array</span>(length2).fill(<span class="number">0</span>);</span><br><span class="line">    &#125;);<span class="comment">//快速定义二维数组</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//find()方法返回满足回调条件的数组中第一个元素的值。否则将返回未定义</span></span><br><span class="line"><span class="comment">//forEach()方法遍历数组,foreach中this指向为undefine</span></span><br><span class="line"><span class="comment">//indexOf()；includes()；均用于查询数组中是否包含某个元素</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//join()将数组中的所有元素(或类似数组的对象)连接到一个字符串中，默认为逗号</span></span><br><span class="line"><span class="keyword">var</span> a = [<span class="string">'Wind'</span>, <span class="string">'Rain'</span>, <span class="string">'Fire'</span>];</span><br><span class="line">a.join();    <span class="comment">// 'Wind,Rain,Fire'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//splice()方法通过删除现有元素和/或添加新元素来更改数组的内容。</span></span><br><span class="line">array.splice(start, deleteCount, item1, item2);</span><br><span class="line">myFish.splice(<span class="number">2</span>, <span class="number">1</span>); <span class="comment">// remove 1 item at 2-index position (that is, "drum")</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//slice()切片</span></span><br><span class="line"><span class="built_in">Array</span>.prototype.slice();<span class="comment">//取出任意元素，参数一：从哪开始；参数二：(可选)结束位置。</span></span><br></pre></td></tr></table></figure>

<h2 id="5、bind、call、apply的区别"><a href="#5、bind、call、apply的区别" class="headerlink" title="5、bind、call、apply的区别"></a>5、bind、call、apply的区别</h2><p><strong>相同点：均用于改变函数的上下文，即this指向。</strong></p>
<p>fn.bind： 不会立即调用，而是返回一个绑定后的新函数。fn.call：立即调用，返回函数执行结果，this指向第一个参数，后面可有多个参数，并且这些都是fn函数的参数。fn.apply：立即调用，返回函数的执行结果，this指向第一个参数，第二个参数是个数组，这个数组里内容是fn函数的参数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sub</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> sub = a + b</span><br><span class="line">    <span class="built_in">console</span>.log(sub)</span><br><span class="line">    <span class="keyword">return</span> sub</span><br><span class="line">&#125;</span><br><span class="line">sub.call(<span class="literal">null</span>, <span class="number">1</span>, <span class="number">2</span>)</span><br><span class="line">sub.apply(<span class="literal">null</span>, [<span class="number">1</span>, <span class="number">2</span>]) </span><br><span class="line">sub.bind(<span class="literal">null</span>, <span class="number">1</span>, <span class="number">2</span>)()</span><br></pre></td></tr></table></figure>

<h2 id="6、new的原理"><a href="#6、new的原理" class="headerlink" title="6、new的原理"></a>6、new的原理</h2><p><strong>1、创建一个新对象；2、将构造函数与新对象在原型链中联系起来，即新对象的proto要指向构造函数的原型对象；3、执行构造函数，并将构造函数的初始属性都挂载在新对象上。</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_new</span> (<span class="params">constructor, ...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;;</span><br><span class="line">    obj._proto_ = <span class="keyword">constructor</span>.prototype;</span><br><span class="line">    let result = <span class="keyword">constructor</span>.call(obj, ...args);</span><br><span class="line">    //在obj中执行构造函数,并将构造函数的属性挂载到对象上；</span><br><span class="line">    return (typeof result === 'object') ? result : obj;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="7、如何正确判断this"><a href="#7、如何正确判断this" class="headerlink" title="7、如何正确判断this"></a>7、如何正确判断this</h2><p><strong>核心原理：this的指向在函数定义的时候是确定不了的，只有函数执行的时候才能确定，this最终指向调用它的对象；同样，不管有多少层级的调用，this也只是指向它上一级的对象。</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1、不管多少层调用，指向调用时的上一层对象。</span></span><br><span class="line"><span class="keyword">var</span> flora = &#123;</span><br><span class="line">    Animal:<span class="string">"a"</span>,</span><br><span class="line">    mars:&#123;</span><br><span class="line">        Animal:<span class="string">"b"</span>,</span><br><span class="line">        say:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; </span><br><span class="line">            <span class="built_in">console</span>.log(<span class="keyword">this</span>.Animal);</span><br><span class="line">    	&#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line">flora.mars.say();<span class="comment">//输出为b</span></span><br><span class="line"><span class="comment">//2、定义时不决定this，指向调用时的对象</span></span><br><span class="line"><span class="keyword">var</span> flora1 = &#123;</span><br><span class="line">    Animal:<span class="string">"a"</span>,</span><br><span class="line">    mars:&#123;</span><br><span class="line">        Animal:<span class="string">"b"</span>,</span><br><span class="line">        say:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; </span><br><span class="line">            <span class="built_in">console</span>.log(<span class="keyword">this</span>);</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="keyword">this</span>.Animal);</span><br><span class="line">    	&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> pink = flora.mars.say;</span><br><span class="line">pink();<span class="comment">//输出分别为window和undefine，因为pink()在全局环境上调用，因此this为window。</span></span><br><span class="line"><span class="comment">//3、new会改变this的指向</span></span><br><span class="line"><span class="comment">/*但当构造函数有返回值时，又不一样了，</span></span><br><span class="line"><span class="comment">如果返回的是一个对象：this会指向哪个返回的对象。</span></span><br><span class="line"><span class="comment">如果返回的不是一个对象：this还是指向那个函数的实例 */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">flora</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.animal = <span class="string">"a"</span>;   </span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> blue = <span class="keyword">new</span> flora();</span><br><span class="line"><span class="built_in">console</span>.log(blue.animal); <span class="comment">//a</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">flora</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.animal = <span class="string">"a"</span>;   </span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> blue = <span class="keyword">new</span> flora();</span><br><span class="line"><span class="built_in">console</span>.log(blue.animal); <span class="comment">//undefined</span></span><br></pre></td></tr></table></figure>

<h2 id="8、闭包"><a href="#8、闭包" class="headerlink" title="8、闭包"></a>8、闭包</h2><p>闭包：有权访问另一个函数作用域中的变量的函数。<strong>闭包可以让一个函数访问并操作其声明时的作用域中的变量和函数，并且，即使声明时的作用域消失了，也可以调用</strong>。要注意的是：闭包不是在创建的那一时刻点的状态的快照，而是一个真实的封装，只要闭包存在，就可以对其进行修改。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//最常用的：1、封装私有变量：</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Ninja</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> feints = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">this</span>.getFeints = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> feints;<span class="comment">//在构造函数外部的代码无法访问feints变量，只能通过办读方式访问</span></span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">this</span>.feint = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        feints++;<span class="comment">//声明一个累加方法，由于feints为私有变量，因此在外部无法累加</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> ninja1 = <span class="keyword">new</span> Ninja();</span><br><span class="line"><span class="built_in">console</span>.log(ninja1.feints === <span class="literal">undefined</span>);<span class="comment">//true，验证我们无法直接获取该变量值</span></span><br><span class="line">ninja1.feint();</span><br><span class="line"><span class="built_in">console</span>.log(ninja1.getFeints() === <span class="number">1</span>);<span class="comment">//true, 可通过getFeints方法操作该变量值</span></span><br><span class="line"><span class="keyword">let</span> ninja2 = <span class="keyword">new</span> Ninja();</span><br><span class="line"><span class="built_in">console</span>.log(ninja2.getFeints() === <span class="number">0</span>);<span class="comment">//true，ninja2对象具有自己私有的feints变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*2、回调函数：</span></span><br><span class="line"><span class="comment">指要在将来不确定的某一时刻异步调用的函数，在这种函数中，通常需要频繁访问外部数据。</span></span><br><span class="line"><span class="comment">在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中，只要使用了回调函数，实际上就是在使用闭包。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*3、闭包的副作用：(1)闭包会携带其函数的作用域，因此会占用更多的内存；</span></span><br><span class="line"><span class="comment">(2)闭包只能取得包含函数中任何变量的最后一个值；*/</span></span><br></pre></td></tr></table></figure>

<h2 id="9、prototype"><a href="#9、prototype" class="headerlink" title="9、prototype"></a>9、prototype</h2><p>显示原型：当你创建一个函数时，JS会为这个函数(别忘了：JS一切皆对象)自动添加prototype属性，这个属性的值是一个对象，也就是原型对象(即函数名.prototype)。显式原型（prototype）只有函数才拥有。我们后面讲的隐式原型则是所有对象都有。</p>
<p>隐式原型：JavaScript中任意对象都有一个内置属性[[prototype]]，在ES5之前没有标准的方法访问这个内置属性，但是大多数浏览器都支持通过__proto__来访问。现在，所谓的隐式原型就是__proto__ 了隐式原型指向创建这个对象的函数的prototype（Object.create函数构造出来的实例有点例为，后面会说明。JavaScript 可以通过prototype和__proto__在两个对象之间创建一个关联，使得一个对象就可以通过委托访问另一个对象的属性和函数。</p>
<h2 id="10、继承"><a href="#10、继承" class="headerlink" title="10、继承"></a>10、继承</h2><p><strong>使用原型链继承，继承了父类的属性和方法，但对于引用属性，由于传入的是其地址，因此多个指向的是同样的父类属性；使用构造函数来实现属性的继承，在子类中调用父类构造函数，从而现实例属性的继承，因此同样子类实例上的属性覆盖了父类的同名属性。</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent3</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = <span class="string">'parent3'</span>;</span><br><span class="line">    <span class="keyword">this</span>.play = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">  &#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child3</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    Parent3.call(<span class="keyword">this</span>);</span><br><span class="line">    <span class="keyword">this</span>.type = <span class="string">'child3'</span>;</span><br><span class="line">  &#125;</span><br><span class="line">Child3.prototype = <span class="keyword">new</span> Parent3();</span><br><span class="line"></span><br><span class="line"><span class="comment">/*寄生组合式继承：简单优化上面的两点：</span></span><br><span class="line"><span class="comment">1、避免parent构造函数执行2次；2、子类的构造函数应该指向Child，而不是Parent</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent5</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = <span class="string">'parent5'</span>;</span><br><span class="line">    <span class="keyword">this</span>.play = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">Child5</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    Parent5.call(<span class="keyword">this</span>);</span><br><span class="line">    <span class="keyword">this</span>.type = <span class="string">'child5'</span>;</span><br><span class="line">  &#125;</span><br><span class="line">Child5.prototype = <span class="built_in">Object</span>.create(Parent5.prototype);</span><br><span class="line">Child5.prototype.constructor = Child5;</span><br></pre></td></tr></table></figure>

<h2 id="11、防抖与节流"><a href="#11、防抖与节流" class="headerlink" title="11、防抖与节流"></a>11、防抖与节流</h2><p><strong>防抖：即短时间内大量触发同一事件，只会执行一次函数。原理：设置一个定时器，约定在xx毫秒之后再触发事件处理器，每次·触发事件都会重新设置处理器，直至xx毫秒内无第二次操作</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span> (<span class="params">func, await</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//传入参数分别为需要添加防抖的事件函数，和防抖的时间间隔</span></span><br><span class="line">    <span class="keyword">let</span> timeout = &#123;&#125;;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">let</span> context = <span class="keyword">this</span>;</span><br><span class="line">        <span class="keyword">let</span> args = <span class="built_in">arguments</span>;</span><br><span class="line">        <span class="keyword">if</span> (timeout) clearTimeout(timeout);<span class="comment">//每次触发都会重置定时器</span></span><br><span class="line">        timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">            func.apply(context, args);</span><br><span class="line">        &#125;, <span class="keyword">await</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>节流：间隔执行，每隔一段时间就执行一次。原理：设置一个定时器，约定xx毫秒后执行时间，如果时间到了，那么执行函数并重置定时器，和防抖的区别是：防抖每次触发事件都重置定时器，而节流在定时器到事件后再清空。</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">throttle</span>(<span class="params">func, wait</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> timeout = <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">let</span> context = <span class="keyword">this</span>;</span><br><span class="line">        <span class="keyword">let</span> args = <span class="built_in">arguments</span>;</span><br><span class="line">        <span class="keyword">if</span> (!timeout) &#123;</span><br><span class="line">            timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">                timeout = <span class="literal">null</span>;</span><br><span class="line">                func.apply(context, args);</span><br><span class="line">            &#125;, wait);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="12、Array-sort"><a href="#12、Array-sort" class="headerlink" title="12、Array.sort()"></a>12、Array.sort()</h2><p>默认情况下，sort()方法按升序排列数组项；且会调用每个数组项的toString()方法，比较字符串；因此直接用于数字比较不会正确。sort()可以接受一个函数作为参数，该函数可以接收两个参数，1、第一个参数应该位于第二个之前，则返回负数；</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> values = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">10</span>, <span class="number">15</span>];</span><br><span class="line">values.sort();</span><br><span class="line">alert(values);<span class="comment">//0, 1, 10 ,15 ,5 字符串比较时，10在5的前面，因此数组顺序被改变</span></span><br><span class="line">values.sort(<span class="function"><span class="keyword">function</span> <span class="title">compare</span> (<span class="params">value1, value2</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> value1 - value2;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">//当value1小于value2时，返回负数，小的放在前面，因此为升序排列。</span></span><br></pre></td></tr></table></figure>

<p>原理思路：基本上使用的是快速排序的方法。设要排序的元素个数是n：1、当 n &lt;= 10 时，采用插入排序；2、当 n &gt; 10 时，采用三路快速排序；3、10 &lt; n &lt;= 1000, 采用中位数作为哨兵元素；4、n &gt; 1000, 每隔 200~215 个元素挑出一个元素，放到一个新数组，然后对它排序，找到中间位置的数，以此作为中位数。</p>
<p>为什么要花这么大的力气选择哨兵元素？因为快速排序的性能瓶颈在于递归的深度，最坏的情况是每次的哨兵都是最小元素或者最大元素，那么进行partition(一边是小于哨兵的元素，另一边是大于哨兵的元素)时，就会有一边是空的，那么这么排下去，递归的层数就达到了n, 而每一层的复杂度是O(n)，因此快排这时候会退化成O(n^2)级别。</p>
<h2 id="13、Ajax的请求过程"><a href="#13、Ajax的请求过程" class="headerlink" title="13、Ajax的请求过程"></a>13、Ajax的请求过程</h2><p><strong>我们常用的 ajax 就是通过 XMLHttpRequest 对象实现的，这个对象有很多的属性和事件，在使用之前，我们需要先将它实例化.实例化后，我们就可以通过 xhr 来发起一个请求。</strong></p>
<p>xhr 具有一个 open 方法，这个方法的作用类似于初始化，并不会发起真正的请求；open 方法具有 5 个参数，但是常用的是前 3 个method： 请求方式 —— get / post；url：请求的地址；async：是否异步请求，默认为 true（异步）。send 方法发送请求，并接受一个可选参数，当请求方式为 post 时，可以将请求体的参数传入，当请求方式为 get 时，可以不传或传入 null，不管是 get 还是 post，参数都需要通过 encodeURIComponent 编码后拼接。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ajax</span>(<span class="params">url, fnSucc, fnFaild</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhttp;</span><br><span class="line">    <span class="comment">// 第一步：创建XMLHttpRequest对象</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">window</span>.XMLHttpRequest) &#123;</span><br><span class="line">        <span class="comment">// 现代浏览器</span></span><br><span class="line">        xhttp = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">     &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// IE6等老版本浏览器</span></span><br><span class="line">        xhttp = <span class="keyword">new</span> ActiveXObject(<span class="string">"Microsoft.XMLHTTP"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 第二步：调用XMLHttpRequest的open函数  </span></span><br><span class="line">    xhttp.open(<span class="string">'GET'</span>, url);</span><br><span class="line">    <span class="comment">// 第三步：XMLHttpRequest向服务器发送请求</span></span><br><span class="line">    xhttp.send();</span><br><span class="line">    <span class="comment">// 第四步：处理响应</span></span><br><span class="line">    xhttp.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="comment">//XMLHttpRequest上有一个方法，名叫onreadystatechange，当请求接收到响应的时候便会触发，在这个方法内部，我们来定义对响应的处理：</span></span><br><span class="line">      <span class="keyword">if</span> (xhttp.readyState === <span class="number">4</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (xhttp.status === <span class="number">200</span>) &#123;</span><br><span class="line">          fnSucc(xhttp.responseText)</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (fnFaild) fnFaild(xhttp.responseText);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="14、JS垃圾回收机制"><a href="#14、JS垃圾回收机制" class="headerlink" title="14、JS垃圾回收机制"></a>14、JS垃圾回收机制</h2><p>周期回收：周期性执行，找出那些不在继续使用的变量，然后释放其内存；标记清除：是当变量进入环境时，将这个变量标记为“进入环境”。当变量离开环境时，则将其标记为“离开环境”。标记“离开环境”的就回收内存。</p>
<h2 id="15、addEventListener"><a href="#15、addEventListener" class="headerlink" title="15、addEventListener"></a>15、addEventListener</h2><p><strong>target.addEventListener(eventType,callback,useCapture)；<code>useCapture</code>：默认为false，在DOM树中冒泡阶段执行回调，设置为true时则在捕获阶段执行回调</strong></p>
<p><strong>事件委托，通俗地来讲，就是把一个元素响应事件（click、keydown……）的函数委托到另一个元素。一般来讲，会把一个或者一组元素的事件委托到它的父层或者更外层元素上，真正绑定事件的是</strong>外层元素，当事件响应到需要绑定的元素上时，会通过事件冒泡机制从而触发它的外层元素的绑定事件上，然后在外层元素上去执行函数。</p>
<p>在 <strong>document.addEventListener</strong> 的时候我们可以<strong>设置事件模型</strong>：事件冒泡、事件捕获，一般来说都是用事件冒泡的模型；捕获阶段：在事件冒泡的模型中，捕获阶段不会响应任何事件； 目标阶段：目标阶段就是指事件响应到触发事件的最底层元素上； 冒泡阶段：冒泡阶段就是事件的触发响应会从最底层目标一层层地向外到最外层（根节点），事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层。</p>
<p> focus、blur 之类的事件本身没有事件冒泡机制，所以无法委托； mousemove、mouseout这样的事件，虽然有事件冒泡，但是只能不断通过位置去计算定位，对性能消耗高，因此也是不适合于事件委托的。</p>
<h2 id="16、weakMap与Map"><a href="#16、weakMap与Map" class="headerlink" title="16、weakMap与Map"></a>16、weakMap与Map</h2><p>WeakMap 对象是一组键/值对的集合，其中的键是弱引用的。其键必须是对象，而值可以是任意的。</p>
<p>什么是<strong>弱引用</strong>呢？</p>
<p>在计算机程序设计中，弱引用与强引用相对，是指不能确保其引用的对象不会被垃圾回收器回收的引用。 一个对象若只被弱引用所引用，则被认为是不可访问（或弱可访问）的，并因此可能在任何时刻被回收。</p>
<p>我们默认创建一个对象：<code>const obj = {}</code>，就默认创建了一个强引用的对象，我们只有手动将<code>obj = null</code>，它才会被垃圾回收机制进行回收，如果是弱引用对象，垃圾回收机制会自动帮我们回收。</p>
<p>如果我们使用<code>Map</code>的话，那么对象间是存在强引用关系的：虽然我们手动将<code>obj</code>，进行释放，然是<code>target</code>依然对<code>obj</code>存在强引用关系，所以这部分内存依然无法被释放。</p>
<p>如果是<code>WeakMap</code>的话，<code>target</code>和<code>obj</code>存在的就是弱引用关系，当下一次垃圾回收机制执行时，这块内存就会被释放掉。</p>
<p>设想一下，如果我们要拷贝的对象非常庞大时，使用<code>Map</code>会对内存造成非常大的额外消耗，而且我们需要手动清除<code>Map</code>的属性才能释放这块内存，而<code>WeakMap</code>会帮我们巧妙化解这个问题。从而避免了内存泄漏的问题。</p>
<h2 id="17、原型与原型链"><a href="#17、原型与原型链" class="headerlink" title="17、原型与原型链"></a>17、原型与原型链</h2><p>在JavaScript中，每当定义一个函数数据类型(普通函数、类)时候，都会天生自带一个prototype属性，这个属性指向函数的原型对象。当函数经过new调用时，这个函数就成为了构造函数，返回一个全新的实例对象，这个实例对象有一个__proto__属性，指向构造函数的原型对象。</p>
<h2 id="18、JS类型转换机制"><a href="#18、JS类型转换机制" class="headerlink" title="18、JS类型转换机制"></a>18、JS类型转换机制</h2><p><strong>JS中，类型转换只有三种：1、转换成数字。2、转换成布尔值。3、转换成字符串。</strong></p>
<p>这里其实有一个经典的问题，就是“JS的**[]==![]和{} ==!{}**”，两者的结果分别是多少？</p>
<p>原则：<br>1.两者类型是否相同，相同就比大小<br>2.类型不相同，进行类型转换<br>3.判断是否在对比 null 和 undefined，是的话就会返回 true<br>4.判断两者类型是否为 string 和 number，是的话就会将字符串转换为 number<br>5.判断其中一方是否为 boolean，是的话就会把 boolean 转为 number 再进行判断<br>6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol，是的话就会把 object 转为原始类型再进行判断</p>
<p><strong>比较[]==![]：</strong><br>1.“!”运算符优先于“==”，优先转化“![]”<br>2.![]-&gt;!true-&gt;false（一元“！”运算符将其操作数转化为布尔值并取反）<br>3.[]==false（一方为 boolean，把 boolean 转为 number 再进行判断）<br>4.[]==0（一方为 object 且另一方为 number，把 object 转为原始类型再进行判断）<br>5.[]-&gt;””(对象转化为原始值,首先调用 valueOf() 方法只能得到本身,则调用 toString() 方法）<br>6.””==0（string 和 number比较，将字符串转换为 number）<br>7.0==0：true</p>
<p><strong>比较{}==!{}：</strong><br>1.“!”运算符优先于“==”，优先转化“!{}”<br>2.!{}-&gt;!true-&gt;false（一元“！”运算符将其操作数转化为布尔值并取反）<br>3.{}==false（一方为 boolean，把 boolean 转为 number 再进行判断）<br>4.{}==0（一方为 object 且另一方为 number，把 object 转为原始类型再进行判断）<br>5.{}-&gt;”[object Object]”(对象转化为原始值,首先调用 valueOf() 方法只能得到本身,则调用 toString() 方法）<br>6.”[object Object]”==0（string 和 number比较，将字符串转换为 number）<br>7.NaN==0：false</p>
<h2 id="19、JavaScript的执行上下文"><a href="#19、JavaScript的执行上下文" class="headerlink" title="19、JavaScript的执行上下文"></a>19、JavaScript的执行上下文</h2><p>在JavaScript中有三种代码运行环境：</p>
<ul>
<li>Global Code<ul>
<li>JavaScript代码开始运行的默认环境</li>
</ul>
</li>
<li>Function Code<ul>
<li>代码进入一个JavaScript函数</li>
</ul>
</li>
<li>Eval Code<ul>
<li>使用eval()执行代码</li>
</ul>
</li>
</ul>
<p>为了表示不同的运行环境，JavaScript中有一个<strong>执行上下文（Execution context，EC）</strong>的概念。也就是说，当JavaScript代码执行的时候，会进入不同的执行上下文，这些执行上下文就构成了一个<strong>执行上下文栈（Execution context stack，ECS）</strong>。</p>
<p>当JavaScript代码执行的时候，第一个进入的总是默认的Global Execution Context，所以说它总是在ECS的最底部。</p>
<p>对于每个Execution Context都有三个重要的属性，<strong>变量对象（Variable object，VO），作用域链（Scope chain）和this</strong>。这三个属性跟代码运行的行为有很重要的关系，下面会一一介绍。执行上下文决定了三个属性：变量对象、作用域链、this。</p>
<p><strong>变量对象</strong>：变量对象是与执行上下文相关的数据作用域。它是一个与上下文相关的特殊对象，其中存储了在上下文中定义的变量和函数声明。它会包含以下信息：变量、函数声明、函数的形参。</p>
<p><strong>活动对象</strong>：在函数执行上下文中，VO是不能直接访问的，此时由激活对象(Activation Object,缩写为AO)扮演VO的角色。激活对象 是在进入函数上下文时刻被创建的，它通过函数的arguments属性初始化。</p>
<p>Arguments Objects 是函数上下文里的激活对象AO中的内部对象，它包括下列属性：callee：指向当前函数的引用；length： 真正传递的参数的个数；properties-indexes：就是函数的参数值(按参数列表从左到右排列)。</p>
<p>对于VO和AO的关系可以理解为，VO在不同的Execution Context中会有不同的表现：当在Global Execution Context中，可以直接使用VO；但是，在函数Execution Context中，AO就会被创建，在函数执行上下文中，就会创建出活动对象。</p>
<p><strong>执行上下文的创建阶段</strong>：当一段JavaScript代码执行的时候，JavaScript解释器会创建Execution Context，其实这里会有两个阶段：</p>
<ul>
<li>创建阶段（当函数被调用，但是开始执行函数内部代码之前）<ul>
<li>创建Scope chain</li>
<li>创建VO/AO（variables, functions and arguments）</li>
<li>设置this的值</li>
</ul>
</li>
<li>激活/代码执行阶段<ul>
<li>设置变量的值、函数的引用，然后解释/执行代码</li>
</ul>
</li>
</ul>
<p>这里想要详细介绍一下”创建VO/AO”中的一些细节，因为这些内容将直接影响代码运行的行为。</p>
<p>对于”创建VO/AO”这一步，JavaScript解释器主要做了下面的事情：</p>
<ul>
<li>根据函数的参数，创建并初始化arguments object</li>
<li>扫描函数内部代码，查找函数声明（Function declaration）<ul>
<li>对于所有找到的函数声明，将函数名和函数引用存入VO/AO中。对于函数声明，则会立即将引入存进V0/AO中，此时便可以显示正常结果。</li>
<li><strong>如果VO/AO中已经有同名的函数，那么就进行覆盖</strong></li>
</ul>
</li>
<li>扫描函数内部代码，查找变量声明（Variable declaration）<ul>
<li>对于所有找到的变量声明，将变量名存入VO/AO中，并初始化为”undefined”。（定义的变量会先将其初始化为undefined值）</li>
<li>如果变量名称跟已经声明的形式参数或函数相同，则变量声明不会干扰已经存在的这类属性</li>
</ul>
</li>
</ul>
<p><strong>实例分析</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(bar);</span><br><span class="line">    <span class="built_in">console</span>.log(baz);</span><br><span class="line">    <span class="keyword">var</span> bar = <span class="number">20</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">baz</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"baz"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;)()</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">代码解释：匿名函数会首先进入"创建阶段"，JavaScript解释器会创建一个"Function Execution Context"，然后创建Scope chain，VO/AO和this。根据前面的介绍，解释器会扫描函数和变量声明，如下的AO会被创建：</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">因此输出结果：</span></span><br><span class="line"><span class="comment">	undefined；</span></span><br><span class="line"><span class="comment">	function baz()&#123; console.log("baz"); &#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(bar);<span class="comment">//这个会报错，is not defined</span></span><br><span class="line">    <span class="built_in">console</span>.log(baz);</span><br><span class="line">    </span><br><span class="line">    bar = <span class="number">20</span>;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">window</span>.bar);</span><br><span class="line">    <span class="built_in">console</span>.log(bar);</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">baz</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"baz"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;)()</span><br><span class="line"><span class="comment">/*同理，很简单，</span></span><br><span class="line"><span class="comment">因此输出结果：</span></span><br><span class="line"><span class="comment">	function baz()&#123; console.log("baz"); &#125;</span></span><br><span class="line"><span class="comment">	20</span></span><br><span class="line"><span class="comment">	20</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(foo);</span><br><span class="line">    <span class="built_in">console</span>.log(bar);</span><br><span class="line">    <span class="built_in">console</span>.log(baz);</span><br><span class="line">    <span class="keyword">var</span> foo = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"bar"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> bar = <span class="number">20</span>;</span><br><span class="line">    <span class="built_in">console</span>.log(bar);</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">baz</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"baz"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)()</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">最后这个才是重头戏，</span></span><br><span class="line"><span class="comment">代码的输出结果为：</span></span><br><span class="line"><span class="comment">	undefined</span></span><br><span class="line"><span class="comment">	function bar()&#123; console.log("bar"); &#125;</span></span><br><span class="line"><span class="comment">	function baz()&#123; console.log("baz"); &#125;</span></span><br><span class="line"><span class="comment">	20</span></span><br><span class="line"><span class="comment">	</span></span><br><span class="line"><span class="comment">代码中，最"奇怪"的地方应该就是"bar"的输出了，第一次是一个函数，第二次是"20"。</span></span><br><span class="line"><span class="comment">其实也很好解释，回到前面对"创建VO/AO"的介绍，在创建VO/AO过程中，解释器会先扫描函数声明，然后"foo: &lt;function&gt;"就被保存在了AO中；但解释器扫描变量声明的时候，虽然发现"var bar = 20;"，但是因为"foo"在AO中已经存在，所以就没有任何操作了。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">但是，当代码执行到第二句"console.log(bar);"的时候，"激活/代码执行阶段"已经把AO中的"bar"重新设置了。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h2 id="20、JavaScript的作用域链"><a href="#20、JavaScript的作用域链" class="headerlink" title="20、JavaScript的作用域链"></a>20、JavaScript的作用域链</h2><p>在很多语言中，作用域都是通过代码块{}来决定的，但是JavaScript中作用域是跟函数相关的。一般分为全局作用域与函数作用域。</p>
<p><strong>全局作用域</strong>中的对象可以在代码的任何地方访问，一般来说，下面情况的对象会在全局作用域中：</p>
<ul>
<li>最外层函数和在最外层函数外面定义的变量    </li>
<li>没有通过关键字”var”声明的变量</li>
<li>浏览器中，window对象的属性</li>
</ul>
<p><strong>局部作用域</strong>又被称为函数作用域（Function scope），所有的变量和函数只能在作用域内部使用。</p>
<p>通过前面一篇文章了解到，每一个Execution Context中都有一个VO，用来存放变量，函数和参数等信息。在JavaScript代码运行中，所有用到的变量都需要去当前AO/VO中查找，当找不到的时候，就会继续查找上层Execution Context中的AO/VO。这样一级级向上查找的过程，就是所有Execution Context中的AO/VO组成了一个作用域链。</p>
<p>所以说，<strong>作用域链</strong>与一个执行上下文相关，是内部上下文所有变量对象（包括父变量对象）的列表，用于变量查询，这就是原型链与作用域链最为不同的地方。</p>
<p><strong>闭包：</strong>在JavaScript中，闭包跟作用域链有紧密的关系。相信大家对下面的闭包例子一定非常熟悉，代码中通过闭包实现了一个简单的计数器。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">counter</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> x = <span class="number">0</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        increase: <span class="function"><span class="keyword">function</span> <span class="title">increase</span>(<span class="params"></span>) </span>&#123; <span class="keyword">return</span> ++x; &#125;,</span><br><span class="line">        decrease: <span class="function"><span class="keyword">function</span> <span class="title">decrease</span>(<span class="params"></span>) </span>&#123; <span class="keyword">return</span> --x; &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> ctor = counter();</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(ctor.increase());</span><br><span class="line"><span class="built_in">console</span>.log(ctor.decrease());</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">counter Execution Context退出了执行上下文栈，但是counter AO没有销毁，可以继续访问。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<p><strong>作用域链查找：</strong></p>
<p>作用域链（scope chain）的主要作用就是用来进行变量查找。但是，在JavaScript中还有原型链（prototype chain）的概念。</p>
<p>由于作用域链和原型链的相互作用，这样就形成了一个二维的查找。</p>
<p>对于这个二维查找可以总结为：<strong>当代码需要查找一个属性（property）或者描述符（identifier）的时候，首先会通过作用域链（scope chain）来查找相关的对象；一旦对象被找到，就会根据对象的原型链（prototype chain）来查找属性（property）</strong>。</p>
<h2 id="21、JS函数值传递问题"><a href="#21、JS函数值传递问题" class="headerlink" title="21、JS函数值传递问题"></a>21、JS函数值传递问题</h2><h3 id="怎么理解JS函数参数是按值传递"><a href="#怎么理解JS函数参数是按值传递" class="headerlink" title="怎么理解JS函数参数是按值传递"></a>怎么理解JS函数参数是按值传递</h3><p>我们先来看一下这道题：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>];</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">b</span>)</span>&#123;</span><br><span class="line">    b=[<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>];</span><br><span class="line">&#125;</span><br><span class="line">fn(a);</span><br><span class="line"><span class="built_in">console</span>.log(a); <span class="comment">//请问a 输出多少</span></span><br></pre></td></tr></table></figure>

<p>我们接下来再看一道题：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj=&#123;</span><br><span class="line">    name:<span class="string">'大雄'</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">b</span>)</span>&#123;</span><br><span class="line">    b.name=<span class="string">'小熊'</span></span><br><span class="line">&#125;</span><br><span class="line">fn(obj);</span><br><span class="line"><span class="built_in">console</span>.log(obj.name); <span class="comment">// 输出多少</span></span><br></pre></td></tr></table></figure>

<hr>
<p>第一道题答案：[1,2,3];</p>
<p>第二道题答案：小熊；</p>
<p>怎么样你都答对了吗？</p>
<p>接下来我们详解一下为什么</p>
<p>《Javascript 高级程序设计》第三版中有这么一句话 <strong>ECMAScript中所有函数的参数都是按值传递的</strong></p>
<p>但是从第二道题我们明显感觉到：就是按照引用传递的啊；首先我们都知道，js 中的类型分为 值类型和引用类型，值类型保存在内存栈中，引用类型保存在内存堆中；</p>
<p>我们看一下 下面的这段代码：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a=&#123;</span><br><span class="line">  name:<span class="string">'大雄'</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">var</span> b=a;</span><br><span class="line">b.name=<span class="string">'小熊'</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a.name);</span><br></pre></td></tr></table></figure>

<p>这段代码的执行结果想必大家都知道，因为a 保存的是一个堆指针，b赋值后指向了同一个堆内存；</p>
<p><img src="/../../image/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/v2-0077e57c58c08c97d8010db0d1ec2d8d_720w.jpg" alt="img"></p>
<p>我们现在理解下：函数都是按值传递的；</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a=&#123;&#125;;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">b</span>)</span>&#123;</span><br><span class="line">    b=<span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line">fn(a);</span><br><span class="line"><span class="comment">//这段代码中函数的参数传递相当于如下代码</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">b</span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> b=a; <span class="comment">// 对参数进行了复制；在栈内存在开辟了空间；</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>所以说：<strong>值传递</strong> 可以理解为复制变量值，基本类型复制后俩个变量完全独立；引用类型复制的是引用（即指针），之后的任何一方改变都会映射到另一方；</p>
<p>我相信说到这里第二道题的答案大家应该都明白了，接下来我们看一下第一道题：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 第一题 相当于如下的代码</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">b</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> b=a; <span class="comment">// b与a 指向了同一个堆内存；</span></span><br><span class="line">  b=[<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>]; <span class="comment">// 并没有改变指针的内容；而是开辟了一个新的堆空间；所以a,b 就不相互影响了； </span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>我们用图说明一下：</p>
<p><img src="/../../image/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/v2-97a63d2d5761c188ae32b84174e7d2e9_720w.jpg" alt="img"></p>
<p>结合图和代码，我们对程序的执行一目了然，相信大家都明白了。</p>
<p>所以说js中<strong>函数的参数都是按值传递的</strong></p>
<h2 id="22、用var来实现let"><a href="#22、用var来实现let" class="headerlink" title="22、用var来实现let"></a>22、用var来实现let</h2><h2 id="23、JS中作用域链的实现"><a href="#23、JS中作用域链的实现" class="headerlink" title="23、JS中作用域链的实现"></a>23、JS中作用域链的实现</h2><h2 id="24、JS引用类型与值类型存储地址不同"><a href="#24、JS引用类型与值类型存储地址不同" class="headerlink" title="24、JS引用类型与值类型存储地址不同"></a>24、JS引用类型与值类型存储地址不同</h2><h2 id="25、如何判断数组数据类型"><a href="#25、如何判断数组数据类型" class="headerlink" title="25、如何判断数组数据类型"></a>25、如何判断数组数据类型</h2><h2 id="26、instanceOf本质"><a href="#26、instanceOf本质" class="headerlink" title="26、instanceOf本质"></a>26、instanceOf本质</h2><p>检测a的原型链（__proto__）上是否有B.prototype，若有返回true，否则false。</p>
<h2 id="27、静态成员、方法"><a href="#27、静态成员、方法" class="headerlink" title="27、静态成员、方法"></a>27、静态成员、方法</h2><p>静态变量和静态方法是挂在类自身上面的变量和方法。</p>
<p>跟类new出来的东西天生与世隔绝，仿佛是两个平行世界，不会互相影响。</p>
<p>静态的好处就是轻便，不需要new就可以直接赋值和调用，Math.PI就是静态变量，Math.random Math.floor 就是静态方法，全局范围想用就用，没什么限制。</p>
<p>类普通方法和静态方法之间的交互:</p>
<p>类的普通方法里也可以调用自身的静态函数和静态方法，比如在构造函数里搞个计数器来计算当前类被实例化过多少次。</p>
<p>在静态方法中虽然不能访问this，但是你可以把实例作为形参传进静态方法做处理，或者可以在静态方法中搞工厂函数，对某个类进行实例化后返回实例等等。单例模式就是利用静态方法实现的。</p>
<p>ES5继承的时候直接把父类身上的属性直接拷过去，方法直接引用过去，就是继承了。<br>父类有的让子类也有我认为就是实现了继承。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">PersonType</span>(<span class="params">name</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = name;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//静态方法</span></span><br><span class="line">PersonType.create = <span class="function"><span class="keyword">function</span>(<span class="params">name</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> PersonType(name);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//实例方法</span></span><br><span class="line">PersonType.prototype.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>.name)</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">var</span> person = PersonType.create(<span class="string">'zoe'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">由于PersonType.create()使用的数据不依赖PersonType的实例，其会被认为是一个静态方法。</span></span><br><span class="line"><span class="comment">ES6类语法创建了静态成员，只需要在方法或访问器属性名前使用静态注释即可</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PersonClass</span> </span>&#123;</span><br><span class="line">    <span class="comment">//等价于PersonType构造函数</span></span><br><span class="line">    <span class="keyword">constructor</span>(name)&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = name</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//等价于PersonType.prototype.sayName</span></span><br><span class="line">    sayName()&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>.name)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//等价于PersonType.create</span></span><br><span class="line">    <span class="keyword">static</span> create(name)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> PersonClass(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> person = PersonClass.create(<span class="string">'zoe'</span>);</span><br><span class="line"><span class="comment">//不可在实例中访问静态成员，必须要直接在类中访问静态成员，所以是PersonClass.create()</span></span><br></pre></td></tr></table></figure>


    </div>
    
    
    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
        <div class="reward-container">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button onclick="var qr = document.getElementById('qr'); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
      
      <div style="display: inline-block;">
        <img src="/images/alipay.png" alt="Li Yudong 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>Li Yudong
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="http://example.com/2021/07/06/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%9B%9E%E7%AD%94JS%E9%97%AE%E9%A2%98/" title="一句化回答JS问题">http://example.com/2021/07/06/面试总结/一句话回答JS问题/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

    
      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/" rel="tag"># 面试总结</a>
          </div>
    
        

    
        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/06/23/%E5%89%8D%E7%AB%AF/%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E7%9B%B8%E5%85%B3%E9%97%AE%E9%A2%98/" rel="prev" title="文件上传下载相关问题">
      <i class="fa fa-chevron-left"></i> 文件上传下载相关问题
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/07/10/vue%E6%BA%90%E7%A0%81/vue%E5%88%86%E6%9E%90/" rel="next" title="vue分析">
      vue分析 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#前言"><span class="nav-number">1.</span> <span class="nav-text">前言</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1、JS的数据类型"><span class="nav-number">1.1.</span> <span class="nav-text">1、JS的数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2、深拷贝、浅拷贝"><span class="nav-number">1.2.</span> <span class="nav-text">2、深拷贝、浅拷贝</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3、判断数据类型"><span class="nav-number">1.3.</span> <span class="nav-text">3、判断数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4、数组常见API"><span class="nav-number">1.4.</span> <span class="nav-text">4、数组常见API</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5、bind、call、apply的区别"><span class="nav-number">1.5.</span> <span class="nav-text">5、bind、call、apply的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6、new的原理"><span class="nav-number">1.6.</span> <span class="nav-text">6、new的原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7、如何正确判断this"><span class="nav-number">1.7.</span> <span class="nav-text">7、如何正确判断this</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8、闭包"><span class="nav-number">1.8.</span> <span class="nav-text">8、闭包</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9、prototype"><span class="nav-number">1.9.</span> <span class="nav-text">9、prototype</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10、继承"><span class="nav-number">1.10.</span> <span class="nav-text">10、继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11、防抖与节流"><span class="nav-number">1.11.</span> <span class="nav-text">11、防抖与节流</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12、Array-sort"><span class="nav-number">1.12.</span> <span class="nav-text">12、Array.sort()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13、Ajax的请求过程"><span class="nav-number">1.13.</span> <span class="nav-text">13、Ajax的请求过程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#14、JS垃圾回收机制"><span class="nav-number">1.14.</span> <span class="nav-text">14、JS垃圾回收机制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#15、addEventListener"><span class="nav-number">1.15.</span> <span class="nav-text">15、addEventListener</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#16、weakMap与Map"><span class="nav-number">1.16.</span> <span class="nav-text">16、weakMap与Map</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#17、原型与原型链"><span class="nav-number">1.17.</span> <span class="nav-text">17、原型与原型链</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#18、JS类型转换机制"><span class="nav-number">1.18.</span> <span class="nav-text">18、JS类型转换机制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#19、JavaScript的执行上下文"><span class="nav-number">1.19.</span> <span class="nav-text">19、JavaScript的执行上下文</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#20、JavaScript的作用域链"><span class="nav-number">1.20.</span> <span class="nav-text">20、JavaScript的作用域链</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#21、JS函数值传递问题"><span class="nav-number">1.21.</span> <span class="nav-text">21、JS函数值传递问题</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#怎么理解JS函数参数是按值传递"><span class="nav-number">1.21.1.</span> <span class="nav-text">怎么理解JS函数参数是按值传递</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#22、用var来实现let"><span class="nav-number">1.22.</span> <span class="nav-text">22、用var来实现let</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#23、JS中作用域链的实现"><span class="nav-number">1.23.</span> <span class="nav-text">23、JS中作用域链的实现</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#24、JS引用类型与值类型存储地址不同"><span class="nav-number">1.24.</span> <span class="nav-text">24、JS引用类型与值类型存储地址不同</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#25、如何判断数组数据类型"><span class="nav-number">1.25.</span> <span class="nav-text">25、如何判断数组数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#26、instanceOf本质"><span class="nav-number">1.26.</span> <span class="nav-text">26、instanceOf本质</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#27、静态成员、方法"><span class="nav-number">1.27.</span> <span class="nav-text">27、静态成员、方法</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Li Yudong"
      src="/images/author.jpg">
  <p class="site-author-name" itemprop="name">Li Yudong</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">95</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/tiarmor1" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;tiarmor1" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:1157019137@qq.com" title="E-Mail → mailto:1157019137@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Li Yudong</span>
</div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='0,0,0' opacity='0.5' zIndex='-1' count='150' src="/lib1/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib1/anime.min.js"></script>
  <script src="/lib1/velocity/velocity.min.js"></script>
  <script src="/lib1/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  

  
   <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas> 
   <script type="text/javascript" src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script> 
   <script type="text/javascript" src="/js/fireworks.js"></script>
  
</body>
</html>

